package org.eremite.corm.party;

import org.apache.openjpa.persistence.OpenJPAPersistence;
import org.apache.openjpa.persistence.OpenJPAQuery;
import org.eremite.corm.Archetype;
import org.eremite.corm.BaseArchetype;
import org.eremite.corm.party.address.*;
import org.eremite.corm.party.relationship.*;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import java.util.List;

@Stateless(name="BeanManager")
public class BeanManagerImpl<A extends BaseArchetype> implements BeanManager {

    @PersistenceContext(unitName = "party-test-unit", type = PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;

    public void add(Archetype... archs) {
        for(Archetype a : archs) {
            entityManager.persist(a);
        }
    }

    public void update(BaseArchetype... archs){
        for(BaseArchetype a : archs) {
            entityManager.merge(a);
        }
    }

    public void refresh(BaseArchetype... archs) {
        for(BaseArchetype a : archs) {
            entityManager.refresh(entityManager.merge(a));
        }
    }

    public void remove(BaseArchetype... archs) {
        for(BaseArchetype a : archs) {
            entityManager.remove(entityManager.merge(a));
        }
    }

    public void clear(String table) {
        Query query = entityManager.createQuery("DELETE FROM " + table);
        query.executeUpdate();
    }

    public List<A> getList(String table) {

        Query query = entityManager.createQuery("SELECT a from " + table + " as a");
        return (List<A>)query.getResultList();
    }

    public List<Address> getAddresses(){
        Query query = entityManager.createQuery("SELECT a from Address as a LEFT JOIN FETCH a.parties");
        return (List<Address>)query.getResultList();
    }

    public List<AssociatedAddress> getAssociatedAddresses(){
        Query query = entityManager.createQuery("SELECT a from AssociatedAddress as a");
        return query.getResultList();
    }

    public List<EmailAddress> getEmailAddresses(){
        Query query = entityManager.createQuery("SELECT a from EmailAddress as a");
        return query.getResultList();
    }

    public List<GeographicAddress> getGeographicAddresses(){
        Query query = entityManager.createQuery("SELECT a from GeographicAddress as a LEFT JOIN FETCH a.telecomAddresses");
        return query.getResultList();
    }

    public List<ISOCountryCode> getISOCountryCodes(){
        Query query = entityManager.createQuery("SELECT a from ISOCountryCode as a");
        return query.getResultList();
    }

    public List<Locale> getLocales(){
        Query query = entityManager.createQuery("SELECT a from Locale as a");
        return query.getResultList();
    }

    public List<TelecomAddress> getTelecomAddresses(){
        Query query = entityManager.createQuery("SELECT a from TelecomAddress as a LEFT JOIN FETCH a.geographicAddresses");
        return query.getResultList();
    }

    public List<WebPageAddress> getWebPageAddresses(){
        Query query = entityManager.createQuery("SELECT a from WebPageAddress as a");
        return query.getResultList();
    }

    public List<AssignedResponsibility> getAssignedResponsibilities(){
        Query query = entityManager.createQuery("SELECT a from AssignedResponsibility as a LEFT JOIN FETCH a.signatures");
        return query.getResultList();
    }

    public List<Capability> getCapabilities(){
        Query query = entityManager.createQuery("SELECT a from Capability as a");
        return query.getResultList();
    }

    public List<PartyRelationship> getPartyRelationships(){
        Query query = entityManager.createQuery("SELECT a from PartyRelationship as a");
//        OpenJPAQuery q = OpenJPAPersistence.cast(query);
//        q.getFetchPlan().setMaxFetchDepth(0).addFetchGroup("detail");
        return query.getResultList();
    }

    public List<PartyRelationship> getPartyRelationships(String collection){
        Query query = entityManager.createQuery(
                "SELECT a from PartyRelationship as a LEFT JOIN FETCH a." + collection);
        return query.getResultList();
    }

    public List<PartyRelationshipType> getPartyRelationshipTypes(){
        Query query = entityManager.createQuery("SELECT a from PartyRelationshipType as a LEFT JOIN FETCH a.properties");
        return query.getResultList();
    }

    public List<PartyRole> getPartyRoles(){
        Query query = entityManager.createQuery("SELECT a from PartyRole as a LEFT JOIN FETCH a.assignedResponsibilities");
//        OpenJPAQuery q = OpenJPAPersistence.cast(query);
//        q.getFetchPlan().setMaxFetchDepth(0).addFetchGroup("withRelationships");
        return query.getResultList();
    }

    public List<PartyRole> getPartyRoles(String collection){
        Query query = entityManager.createQuery(
                "SELECT a from PartyRole as a LEFT JOIN FETCH a." + collection);
        return query.getResultList();
    }

    public List<PartyRoleType> getPartyRoleTypes(){
        Query query = entityManager.createQuery("SELECT a from PartyRoleType as a LEFT JOIN FETCH a.properties");
        return query.getResultList();
    }

    public List<Responsibility> getResponsibilities(){
        Query query = entityManager.createQuery("SELECT a from Responsibility as a");
        return query.getResultList();
    }

    public List<Organization> getOrganizations(){
        Query query = entityManager.createQuery("SELECT a from Organization as a LEFT JOIN FETCH a.otherOrgNames");
        return query.getResultList();
    }

    public List<OrganizationName> getOrganizationNames(){
        Query query = entityManager.createQuery("SELECT a from OrganizationName as a");
        return query.getResultList();
    }

    public List<Party> getParties(){
        Query query = entityManager.createQuery(
                "SELECT a from Party as a"
        );
        return query.getResultList();
    }
    
    public List<Party> getParties(String collection) {
        Query query = entityManager.createQuery(
                "SELECT a from Party as a LEFT JOIN FETCH a." + collection
        );
        return query.getResultList();
    }

    public List<PartySignature> getPartySignatures(){
        Query query = entityManager.createQuery("SELECT a from PartySignature as a");
        return query.getResultList();
    }

    public List<Person> getPersons(){
        Query query = entityManager.createQuery("SELECT a from Person as a LEFT JOIN FETCH a.pseudonyms");
        return query.getResultList();
    }

    public List<PersonName> getPersonNames(){
        Query query = entityManager.createQuery("SELECT a from PersonName as a");
        return query.getResultList();
    }

    public List<Binding> getBindings(){
        Query query = entityManager.createQuery("SELECT a from Binding as a");
        return query.getResultList();
    }

    public List<BindingValue> getBindingValues(){
        Query query = entityManager.createQuery("SELECT a from BindingValue as a");
        return query.getResultList();
    }

    public List<BindingType> getBindingTypes(){
        Query query = entityManager.createQuery("SELECT a from BindingType as a LEFT JOIN FETCH a.options");
        return query.getResultList();
    }

    public List<RegisteredIdentifier> getRegisteredIdentifiers(){
        Query query = entityManager.createQuery("SELECT a from RegisteredIdentifier as a");
        return query.getResultList();
    }
}
